---
title: স্টেট মডেলিং
description:
  package:bloc ব্যবহার করার সময় স্টেট মডেল করার বিভিন্ন উপায়ের একটি ওভারভিউ।
---

import ConcreteClassAndStatusEnumSnippet from '~/components/modeling-state/ConcreteClassAndStatusEnumSnippet.astro';
import SealedClassAndSubclassesSnippet from '~/components/modeling-state/SealedClassAndSubclassesSnippet.astro';

অ্যাপ্লিকেশনের স্টেট সংগঠিত করার ক্ষেত্রে বিভিন্ন ধরনের পদ্ধতি রয়েছে। প্রতিটিরই
নিজস্ব সুবিধা ও সীমাবদ্ধতা আছে। এই সেকশনে আমরা কয়েকটি পদ্ধতি, তাদের
সুবিধা-অসুবিধা এবং কোন পরিস্থিতিতে কোনটি ব্যবহার করা ভালো — তা দেখব।

নিচের পদ্ধতিগুলো সম্পূর্ণই ঐচ্ছিক এবং শুধুই সুপারিশ। আপনি চাইলে আপনার পছন্দমতো
যেকোনো পদ্ধতি ব্যবহার করতে পারেন। সংক্ষিপ্ত এবং সহজ রাখার জন্য কিছু
উদাহরণ/ডকুমেন্টেশন এই পদ্ধতিগুলো অনুসরণ নাও করতে পারে।

:::tip

নিচের কোড স্নিপেটগুলো মূলত স্টেট স্ট্রাকচারের উপর ফোকাস করা। বাস্তবে, আপনি
চাইলে:

- `package:equatable` থেকে `Equatable` প্রসারিত করতে পারেন
- `package:data_class` থেকে `@Data()` দিয়ে ক্লাস অ্যানোটেট করতে পারেন
- `package:meta` থেকে **@immutable** দিয়ে ক্লাস অ্যানোটেট করতে পারেন
- `copyWith` মেথড ইমপ্লিমেন্ট করতে পারেন
- কনস্ট্রাক্টরে `const` কীওয়ার্ড ব্যবহার করতে পারেন

:::

## Concrete Class and Status Enum

এই পদ্ধতিতে সকল স্টেটের জন্য একটি **সিঙ্গেল কনক্রিট ক্লাস** থাকে এবং একটি `enum`
থাকে যা বিভিন্ন স্ট্যাটাস উপস্থাপন করে। সকল প্রপার্টি nullable করা হয় এবং
বর্তমান স্ট্যাটাস অনুযায়ী ব্যবহার করা হয়। এই পদ্ধতি সবচেয়ে ভালো কাজ করে যখন
স্টেটগুলো একে অপরের থেকে কঠোরভাবে আলাদা নয় বা যখন অনেকগুলো শেয়ারড প্রপার্টি
থাকে।

<ConcreteClassAndStatusEnumSnippet />

#### Pros

- **সিম্পল:** একটি ক্লাস এবং একটি status enum পরিচালনা করা সহজ এবং সব প্রপার্টিই
  সহজে অ্যাক্সেস করা যায়।
- **সংক্ষিপ্ত:** অন্যান্য পদ্ধতির তুলনায় সাধারণত কম লাইনের কোড লাগে।

#### Cons

- **টাইপ সেফ নয়:** প্রপার্টিতে অ্যাক্সেস করার আগে `status` চেক করতে হয়। ভুল
  স্টেট `emit` করা সম্ভব, যা বাগ তৈরি করতে পারে। নির্দিষ্ট স্টেটের প্রপার্টি
  nullable হওয়ায় null-check বা force unwrap করতে হয়, যা ঝামেলাযুক্ত হতে পারে।
  ইউনিট টেস্ট এবং বিশেষায়িত নামযুক্ত কনস্ট্রাক্টর লিখে এগুলোর কিছুটা কমানো
  যায়।
- **Bloated:** সময়ের সাথে সাথে অনেক প্রপার্টি জমে একে ভারী ও জটিল করে ফেলতে
  পারে।

#### Verdict

এই পদ্ধতি সাধারণ স্টেট বা এমন পরিস্থিতিতে ভালো কাজ করে যেখানে স্টেটগুলো একে
অপরের এক্সক্লুসিভ নয় (যেমন: একটি error snackbar দেখানো হচ্ছে কিন্তু পূর্বের
success স্টেটের ডেটা এখনও দেখানো হচ্ছে)। এটি টাইপ সেফটির খরচে বেশি
ফ্লেক্সিবিলিটি ও সংক্ষিপ্ততা দেয়।

## Sealed Class and Subclasses

এই পদ্ধতিতে একটি **sealed class** থাকে যা শেয়ারড প্রপার্টিগুলো রাখে এবং প্রতিটি
আলাদা স্টেটের জন্য আলাদা সাবক্লাস থাকে। এটি আলাদা ও এক্সক্লুসিভ স্টেটগুলোর জন্য
অসাধারণভাবে কার্যকর।

<SealedClassAndSubclassesSnippet />

#### Pros

- **টাইপ সেফ:** কম্পাইল-টাইম সেফটি থাকে এবং ভুল প্রপার্টিতে ভুলবশত অ্যাক্সেস করা
  যায় না। প্রতিটি সাবক্লাস তার নিজস্ব প্রপার্টি রাখে, ফলে কোন প্রপার্টি কোন
  স্টেটে তা খুব পরিষ্কার।
- **স্পষ্ট:** শেয়ারড প্রপার্টি এবং স্টেট-নির্দিষ্ট প্রপার্টিগুলো আলাদা রাখা
  যায়।
- **Exhaustive:** `switch` স্টেটমেন্ট ব্যবহার করে প্রত্যেকটি স্টেট স্পষ্টভাবে
  হ্যান্ডেল হচ্ছে কিনা তা নিশ্চিত করা যায়।
  - যদি আপনি
    [exhaustive switching](https://dart.dev/language/branches#exhaustiveness-checking)
    না চান অথবা পরে নতুন subtype যোগ করতে চান API ভাঙা ছাড়া, তাহলে
    [final](https://dart.dev/language/class-modifiers#final) modifier ব্যবহার
    করুন।
  - বিস্তারিত জানতে দেখুন:
    [sealed class documentation](https://dart.dev/language/class-modifiers#sealed)

#### Cons

- **বিস্তারিত/Verbose:** বেশি কোড লাগে (একটি বেস ক্লাস এবং প্রতিটি স্টেটের জন্য
  একটি করে সাবক্লাস)। এছাড়াও, সাবক্লাসগুলোতে শেয়ারড প্রপার্টি পুনরাবৃত্তি করতে
  হতে পারে।
- **জটিল:** নতুন প্রপার্টি যোগ করতে চাইলে প্রতিটি সাবক্লাস এবং বেস ক্লাসে আপডেট
  করতে হয়, যা জটিলতা বাড়াতে পারে। অতিরিক্ত টাইপ-চেকিং লাগতে পারে কিছু
  ক্ষেত্রে।

#### Verdict

এই পদ্ধতি সবচেয়ে ভালো কাজ করে যখন স্টেটগুলো সুস্পষ্টভাবে আলাদা ও এক্সক্লুসিভ
এবং প্রতিটির নিজস্ব প্রপার্টি থাকে। এটি টাইপ সেফটি, স্পষ্টতা এবং exhaustiveness
চেক প্রদান করে এবং সংক্ষিপ্ততার চেয়ে নিরাপত্তাকে বেশি গুরুত্ব দেয়।
